package com.example.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.example.comment.pojo.Comment;
import com.example.comment.pojo.CommentLike;
import com.example.comment.pojo.CommentVo;
import com.example.comment.service.CommentService;
import com.example.common.util.R;
import com.example.common.util.ResultCodeRecord;
import com.example.feignapi.article.ArticleClient;
import com.example.feignapi.user.UserClient;
import com.example.model.article.pojo.ArticleConfig;
import com.example.model.comment.dto.CommentDto;
import com.example.model.comment.dto.CommentLikeDto;
import com.example.model.comment.dto.CommentSaveDto;
import com.example.model.mess.UpdateArticleMess;
import com.example.model.user.pojo.User;
import com.example.utils.thread.UserThreadLocal;
import io.searchbox.strings.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.common.util.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.example.common.constants.HotArticleConstants.HOT_ARTICLE_SCORE_TOPIC;

@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    private UserClient userClient;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private ArticleClient articleClient;
    @Autowired
    private KafkaTemplate< String, String > kafkaTemplate;

    @Override
    public boolean saveComment(CommentSaveDto commentSaveDto) {
        // 1、检查参数
        if (commentSaveDto == null || StringUtils.isBlank(commentSaveDto.getContent()) || commentSaveDto.getArticleId() == null) {
            return R.error(ResultCodeRecord.PARAM_INVALID).isFlag();
        }

        // 校验文章是否可以评论 （我用了checkParam的按照ID查看的）
        if (!checkParam(commentSaveDto.getArticleId())) {
            return R.error(ResultCodeRecord.PARAM_INVALID, "改文章评论权限已经关闭").isFlag();
        }
        if (commentSaveDto.getContent().length() > 140) {
            return R.error(ResultCodeRecord.PARAM_INVALID, "评论内容不超过140字").isFlag();
        }

        // 2、判断是否登录
        User user = UserThreadLocal.getUser();
        if (user == null) {
            return R.error(ResultCodeRecord.NEED_LOGIN).isFlag();
        }

        // 3、安全检查 子航实现
        // 4、保存评论
        User user1 = userClient.getUserByUserId(user.getUserId());
        if (user1 == null) {
            return R.error(ResultCodeRecord.PARAM_INVALID).isFlag();
        }
        Comment comment = new Comment();
        comment.setAuthorId(user.getUserId());
        comment.setContent(commentSaveDto.getContent());
        comment.setCreatedTime(new Date());
        comment.setUpdatedTime(new Date());
        comment.setEntryId(commentSaveDto.getArticleId());
        comment.setImage(user1.getUserImage());
        comment.setAuthorName(user1.getUserName());
        comment.setLikes(0);
        comment.setReply(0);
        comment.setType((short) 0);
        comment.setFlag((short) 0);
        mongoTemplate.save(comment);
        // 5、发送消息，进行聚合
        UpdateArticleMess updateArticleMess = new UpdateArticleMess();
        updateArticleMess.setArticleId(commentSaveDto.getArticleId());
        updateArticleMess.setAdd(1);
        updateArticleMess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
        kafkaTemplate.send(HOT_ARTICLE_SCORE_TOPIC, JSON.toJSONString(commentSaveDto));
        return true;
    }

    @Override
    public Object likeComment(CommentLikeDto commentLikeDto) {
        // 1、检查参数
        if (commentLikeDto == null || commentLikeDto.getCommentId() == null) {
            return R.error(ResultCodeRecord.PARAM_INVALID);
        }
        // 2、判断是否登录
        User user = UserThreadLocal.getUser();
        if (user == null) {
            return R.error(ResultCodeRecord.NEED_LOGIN);
        }
        // 3、安全检查 子航实现
        // 4、保存评论
        Comment comment = mongoTemplate.findById(commentLikeDto.getCommentId(), Comment.class);
        // 5、点赞
        if (comment != null && commentLikeDto.getOperation() == 0) {
            // 更新评论点赞数量
            comment.setLikes(comment.getLikes() + 1);
            mongoTemplate.save(comment);

            // 保存评论点赞数据
            CommentLike commentLike = new CommentLike();
            commentLike.setCommentId(comment.getId());
            commentLike.setAuthorId(user.getUserId());
            mongoTemplate.save(commentLike);
        } else {
            // 更新评论点赞数量
            Integer tmp = comment.getLikes() - 1;
            comment.setLikes(tmp < 1 ? 0 : tmp);
            mongoTemplate.save(comment);

            // 删除评论点赞
            Query query = Query.query(Criteria.where("commentId").is(comment.getId()).and("authorId").is(user.getUserId()));
            mongoTemplate.remove(query, CommentLike.class);
        }

        // 6、取消点赞
        Map<String, Object> map = new HashMap<>();
        map.put("likes", comment.getLikes());
        return map;
    }

    @Override
    public Object getByArticleId(CommentDto commentDto) {
        // 1、检查参数
        if (commentDto == null || commentDto.getArticleId() == null) {
            return R.error(ResultCodeRecord.PARAM_INVALID);
        }
        Integer size = 10;

        // 2、加载数据
        Query query = Query.query(Criteria.where("entryId").is(commentDto.getArticleId()).and("createdTime").lt(commentDto.getMinDate()));
        query.with(Sort.by(Sort.Direction.DESC, "createdTime")).limit(size);
        List<Comment> commentList = mongoTemplate.find(query, Comment.class);

        // 3、数据封装返回
        // 3、1 用户未登录
        User user = UserThreadLocal.getUser();
        if (user == null) {
            return R.ok("按照文章编号查看成功").data("commentList", commentList);
        }

        // 3、2 用户已登录
        // 需要查询当前评论中那些数据被点赞了
        List<String> strings = commentList.stream().map(Comment::getId).toList();
        Query query1 = Query.query(Criteria.where("commentId").in(strings).and("authorId").is(user.getUserId()));
        List<CommentLike> commentLikeList = mongoTemplate.find(query1, CommentLike.class);
        if (commentLikeList == null) {
            return R.ok("按照文章编号查看成功").data("commentList", commentList);
        }

        List< CommentVo > commentVoList = new ArrayList<>();
        for (Comment comment : commentList) {
            CommentVo commentVo = new CommentVo();
            BeanUtils.copyProperties(comment, commentVo);
            for (CommentLike commentLike : commentLikeList) {
                if (comment.getId().equals(commentLike.getCommentId())) {
                    commentVo.setOperation((short) 0);
                    break;
                }
            }
            commentVoList.add(commentVo);
        }
        return commentVoList;
    }

    /**
     * 校验文章是否可以评论
     *
     * @param articleId
     * @return
     */
    private boolean checkParam(Long articleId) {
        //是否可以评论
        R r = articleClient.getArticleConfigByArticleId(articleId);
        if (!r.getCode().equals(200) || r.getData() == null) {
            return false;
        }

        ArticleConfig articleConfig = JSON.parseObject(JSON.toJSONString(r.getData()), ArticleConfig.class);
        if (articleConfig == null && articleConfig.getIsComment()) {
            return false;
        }
        return true;
    }
}